package data

import (
	"context"
	"platform-sastay-file/internal/biz"
	"platform-sastay-file/internal/conf"
	"sort"

	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-redis/redis/v8"
)

type clusterRepo struct {
	log  *log.Helper
	conf *conf.Data
	data *Data
}

func NewClusterRepo(logger log.Logger, conf *conf.Data, data *Data) biz.ClusterRepo {
	return &clusterRepo{
		log:  log.NewHelper(log.With(logger, "module", "repo/cluster")),
		conf: conf,
		data: data,
	}
}

// TagUseNode 标记使用过节点
func (c *clusterRepo) TagUseNode(ctx context.Context, clusterName, ip string) error {
	_, err := c.data.redis.ZIncrBy(ctx, clusterName, 1, ip).Result()
	if err != nil {
		return err
	}
	// todo 重置调用次数
	return nil
}

// VoteRotateNode 轮询选举节点
func (c *clusterRepo) VoteRotateNode(ctx context.Context, clusterName string, nodes []string) (string, error) {
	if len(nodes) == 0 {
		return "", biz.ErrClusterNotFound
	}
	scoreArr := make([]int, 0, len(nodes))
	rankIndex := make(map[int]string, len(nodes))
	for i := range nodes {
		score, err := c.data.redis.ZScore(ctx, clusterName, nodes[i]).Result()
		// 未使用过节点优先返回
		if err == redis.Nil {
			return nodes[i], nil
		}
		if err != nil {
			return "", err
		}
		scoreArr = append(scoreArr, int(score))
		rankIndex[int(score)] = nodes[i]
	}
	sort.Ints(scoreArr)
	return rankIndex[scoreArr[0]], nil
}
